
| 
页目录表或页 表的表项格式  | 
BIT31—BIT12 | BIT11—BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 | 
| 物理页码 | AVL | 0 | 0 | D | A | 0 | 0 | U/S | R/W | P | 
    mov     eax,cr3
    mov     cr3,eax
| 页级 保护 属性  | 
U/S | R/W | 用户级访问权限 | 系统级访问权限 | 
| 0 | 0 | 无 | 读/写/执行 | |
| 0 | 1 | 无 | 读/写/执行 | |
| 1 | 0 | 读/执行 | 读/写/执行 | |
| 1 | 1 | 读/写/执行 | 读/写/执行 | 
| 组合页的 保护>属性  | 
目录表项U/S | 页表项U/S | 组合U/S | 目录表项R/W | 页表项R/W | 组合R/W | 
| 0 | 0 | 0 | 0 | 0 | 0 | |
| 0 | 1 | 0 | 0 | 1 | 0 | |
| 1 | 0 | 0 | 1 | 0 | 0 | |
| 1 | 1 | 1 | 1 | 1 | 1 | 
| 出错码 的格式  | 
BIT15—BIT3 | BIT2 | BIT1 | BIT0 | 
| 未使用 | U | W | P | 
;名称:ASM10.ASM
;功能:演示使用分页管理机制
;编译:TASM ASM10.ASM
;连接:TLINK ASM10.OBJ
;============================================================================
INCLUDE         386SCD.INC
;============================================================================
PDT_AD          =       200000h ;页目录表所在物理页的地址
PT0_AD          =       202000h ;页表0所在物理页的地址
PT1_AD          =       201000h ;页表1所在物理页的地址
PhVB_AD         =       0b8000h ;物理视频缓冲区地址
LoVB_AD         =       0f0000h ;程序使用的逻辑视频缓冲区地址
MPVB_AD         =       301000h ;线性地址0B8000H所映射的物理地址
PhSC_AD         =       303000h ;部分演示代码所在内存的物理地址
LoSC_AD         =       402000h ;部分演示代码的逻辑地址
;============================================================================
GDTSeg          SEGMENT PARA USE16                ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
                ;全局描述符表GDT
GDT             LABEL   BYTE
                ;空描述符
DUMMY           Desc    <>
                ;规范段描述符及选择子
Normal          Desc    <0ffffh,,,ATDW,,>
Normal_Sel      =       Normal-GDT
                ;页目录表所在段描述符(在保护方式下初始化时用)及选择子
PDT             Desc    <0fffh,PDT_AD AND 0ffffh,PDT_AD SHR 16,ATDW,,>
PDT_Sel         =       PDT-GDT
                ;页表0所在段描述符(在保护方式下初始化时用)及选择子
PT0             Desc    <0fffh,PT0_AD AND 0ffffh,PT0_AD SHR 16,ATDW,,>
PT0_Sel         =       PT0-GDT
                ;页表1所在段描述符(在保护方式下初始化时用)及选择子
PT1             Desc    <0fffh,PT1_AD AND 0ffffh,PT1_AD SHR 16,ATDW,,>
PT1_Sel         =       PT1-GDT
                ;逻辑视频缓冲区段描述符及选择子
LoVideo         Desc    <3999,LoVB_AD AND 0ffffh,LoVB_AD SHR 16,ATDW,,>
LoVideo_Sel     =       LoVideo-GDT
                ;逻辑上的部分演示代码段的描述符及选择子
LoCode          Desc    <SCodeLen-1,LoSC_AD AND 0ffffh,LoSC_AD SHR 16,ATCE,,>
LoCode_Sel      =       LoCode-GDT
                ;预定内存区域(用于部分演示代码)的段描述符及选择子
TPSCode         Desc    <SCodeLen-1,PhSC_AD AND 0ffffh,PhSC_AD SHR 16,ATDW,,>
TPSCode_Sel     =       TPSCode-GDT
;----------------------------------------------------------------------------
                ;以下是需额外初始化的描述符
EFFGDT          LABEL   BYTE
                ;临时代码段描述符及选择子
TempCode        Desc    <0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel    =       TempCode-GDT
                ;演示代码段描述符及选择子
DemoCode        Desc    <DemoCodeLen-1,DemoCodeSeg,,ATCE,,>
DemoCode_Sel    =       DemoCode-GDT
                ;演示任务数据段描述符及选择子
DemoData        Desc    <DemoDataLen-1,DemoDataSeg,,ATDW,,>
DemoData_Sel    =       DemoData-GDT
                ;初始化时要移动的代码段描述符及选择子(移动时作为数据对待)
SCode           Desc    <SCodeLen-1,SCodeSeg,,ATDR,,>
SCode_Sel       =       SCode-GDT
;----------------------------------------------------------------------------
GDTLen          =       $-GDT                     ;全局描述符表长度
GDNum           =       ($-EFFGDT)/(SIZE Desc)    ;需特殊处理的描述符数
;----------------------------------------------------------------------------
GDTSeg          ENDS                              ;全局描述符表段定义结束
;============================================================================
;这部分代码在初始化时被复制到预定的内存区域,其功能是在屏幕上显示提示信息
;----------------------------------------------------------------------------
SCodeSeg        SEGMENT PARA USE16
                ASSUME  CS:SCodeSeg,DS:DemoDataSeg
;----------------------------------------------------------------------------
SBegin          PROC    FAR
                mov     ax,LoVideo_Sel
                mov     es,ax
                mov     di,0
                mov     ah,17h
                mov     cx,MessLen
S1:             lodsb
                stosw
                loop    S1
                JUMP16  DemoCode_Sel,Demo3
SBegin          ENDP
;----------------------------------------------------------------------------
MLen            =       $-SBegin
SCodeLen        =       $
SCodeSeg        ENDS
;============================================================================
DemoDataSeg     SEGMENT PARA USE16                ;演示任务数据段
Mess            DB      'Page is OK!'
MessLen         =       $-Mess
DemoDataLen     =       $
DemoDataSeg     ENDS
;============================================================================
DemoCodeSeg     SEGMENT PARA USE16                ;演示任务代码段
                ASSUME  CS:DemoCodeSeg
;----------------------------------------------------------------------------
DemoBegin       PROC    FAR
                mov     ax,PDT_Sel
                mov     es,ax
                xor     di,di
                mov     cx,1024
                xor     eax,eax                   ;先把全部表项置成无效
                rep     stosd                     ;再置表项0和表项1
                mov     DWORD PTR es:[0],PT0_AD OR (USU+RWW+PL)
                mov     DWORD PTR es:[4],PT1_AD OR (USU+RWW+PL)
                mov     ax,PT0_Sel                ;初始化页表0
                mov     es,ax
                xor     di,di
                mov     cx,1024
                xor     eax,eax
                or      eax,USU+RWW+PL
Demo1:          stosd
                add     eax,1000h                 ;先全部置成对应等地址的
                loop    Demo1                     ;物理页,再特别设置两广表项
                mov     di,(PhVB_AD SHR 12)*4
                mov     DWORD PTR es:[di],MPVB_AD+USS+RWW+PL
                mov     di,(LoVB_AD SHR 12)*4
                mov     DWORD PTR es:[di],PhVB_AD+USU+RWR+PL
                mov     ax,PT1_Sel                ;初始化页表1
                mov     es,ax
                xor     di,di
                mov     cx,1024
                mov     eax,400000h
Demo2:          stosd                             ;先把全部表项设置为无效
                add     eax,1000h
                loop    Demo2                     ;再特别设置1项
                mov     di,((LoSC_AD SHR 12)AND 3ffh)*4
                mov     DWORD PTR es:[di],PhSC_AD+USU+RWR+PL
                mov     eax,PDT_AD
                mov     cr3,eax
                mov     eax,cr0
                or      eax,80000000h
                mov     cr0,eax
                jmp     SHORT PageE
PageE:          mov     ax,DemoData_Sel
                mov     ds,ax
                mov     si,OFFSET Mess
                JUMP16  LoCode_Sel,SBegin
Demo3:          mov     eax,cr0
                and     eax,7fffffffh             ;关闭分页机制
                mov     cr0,eax
                jmp     SHORT PageD
PageD:          mov     ax,Normal_Sel
                JUMP16  TempCode_Sel,ToDOS
DemoBegin       ENDP
;----------------------------------------------------------------------------
DemoCodeLen     =       $
DemoCodeSeg     ENDS
;============================================================================
TempCodeSeg     SEGMENT PARA USE16                ;临时任务的代码段
                ASSUME  CS:TempCodeSeg
;----------------------------------------------------------------------------
Virtual         PROC    FAR
                cld                               ;为演示在启用分页机制后执
                mov     ax,SCode_Sel              ;行位于较高线性地址空间中
                mov     ds,ax                     ;的代码作准备
                mov     ax,TPSCode_Sel
                mov     es,ax
                mov     si,OFFSET SBegin
                mov     di,si
                mov     cx,MLen                   ;把分页演示代码复制到预定
                rep     movsb                     ;内存
                JUMP16  DemoCode_Sel,DemoBegin
ToDOS:          mov     ds,ax
                mov     es,ax
                mov     eax,cr0                   ;准备返回实模式
                and     al,11111110b
                mov     cr0,eax
                JUMP16  <SEG Real>,<OFFSET Real>
Virtual         ENDP
;----------------------------------------------------------------------------
TempCodeSeg     ENDS
;============================================================================
RCodeSeg        SEGMENT PARA USE16                ;实方式的初始化代码和数据
                ASSUME  CS:RCodeSeg,DS:RCodeSeg
;----------------------------------------------------------------------------
VGDTR           PDesc   <GDTLen-1,>
;----------------------------------------------------------------------------
Start           PROC
                push    cs
                pop     ds
                cld
                call    InitGDT                   ;初始化全局描述符表GDT
                EnableA20
                lgdt    QWORD PTR VGDTR           ;装载GDTR
                cli                               ;关中断
                mov     eax,cr0
                or      al,1
                mov     cr0,eax
                JUMP16  <TempCode_Sel>,<OFFSET Virtual>
Real:           DisableA20
                sti
                mov     ax,4c00h
                int     21h
Start           ENDP
;----------------------------------------------------------------------------
InitGDT         PROC
                push    ds
                mov     ax,GDTSeg
                mov     ds,ax
                mov     cx,GDNum
                mov     si,OFFSET EFFGDT
InitG:          mov     ax,[si].BaseL
                movzx   eax,ax
                shl     eax,4
                shld    edx,eax,16
                mov     WORD PTR [si].BaseL,ax
                mov     BYTE PTR [si].BaseM,dl
                mov     BYTE PTR [si].BaseH,dh
                add     si,SIZE Desc
                loop    InitG
                pop     ds
                mov     bx,16
                mov     ax,GDTSeg
                mul     bx
                mov     WORD PTR VGDTR.Base,ax
                mov     WORD PTR VGDTR.Base+2,dx
                ret
InitGDT         ENDP
;----------------------------------------------------------------------------
RCodeSeg        ENDS
                END     Start
        mov     eax,cr0
        or      eax,80000000h
        mov     cr0,eax
        jmp     SHORT PageE
PageE:  ...
| 参考资料 | 书 名 | 出 版 社 | 作 者 | 
| 《保护方式下的80386及其编程》 | 清华大学出版社 | 周明德主编 | |
| 《80X86汇编语言程序设计教程》 | 清华大学出版社 | 扬季文主编 |